﻿using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Odyssey.Consul.Implementations
{
    using Features;
    using Http;
    using Models;
    public class Catalog : BaseConsulAPI, ICatalog
    {
        public Catalog(IHttpRequester httpRequester, IConsulConfiguration consulConfiguration) : base(httpRequester, consulConfiguration, EnumResource.Service)
        {
        }

        public async Task ConnectCapableService(string service)
        {
            var path = $"catalog/connect/{service}";
            await ApiSendResponse(path, enumConsulHttpMethod: EnumConsulHttpMethod.Get);
        }

        public async Task<string[]> DatacenterList()
        {
            return await ApiSend<string[]>("catalog/datacenters");
        }

        public async Task Deregister(ArguCatalogDeregister arguDeregister)
        {
            await ApiSendResponse("catalog/deregister", arguDeregister, EnumConsulHttpMethod.Put, requestHeaders: BuildTokenHeader(new EnumResource[] {
                EnumResource.Node,
                EnumResource.Service
            }));
        }

        public async Task<List<ResultNode>> NodeList(ArguCatalogNodeList arguCatalogNodeList)
        {
            QueryParameter queryParameter = null;
            if (arguCatalogNodeList != null)
            {
                queryParameter = null;
                if (!string.IsNullOrWhiteSpace(arguCatalogNodeList.DC))
                {
                    queryParameter.Datacenter = arguCatalogNodeList.DC;

                }
                if (!string.IsNullOrWhiteSpace(arguCatalogNodeList.Near))
                {
                    queryParameter.OtherParameters.Add("near", arguCatalogNodeList.Near);
                }
                if (!string.IsNullOrWhiteSpace(arguCatalogNodeList.NodeMeta))
                {
                    queryParameter.OtherParameters.Add("node-meta", arguCatalogNodeList.NodeMeta);
                }
            }
            var result = await ApiSend<Dictionary<string, ResultNode>>("catalog/nodes", queryParameter: queryParameter, requestHeaders: BuildTokenHeader(EnumResource.Node));
            return result.Select(x => x.Value).ToList();
        }

        public async Task<ResultCatalogNodesForServiceList> NodesForServiceList(ArguCatalogNodesForServiceList arguCatalogNodesForServiceList)
        {
            var path = $"catalog/service/{arguCatalogNodesForServiceList.Service}";
            var queryParameter = new QueryParameter();
            if (!string.IsNullOrWhiteSpace(arguCatalogNodesForServiceList.DC))
            {
                queryParameter.Datacenter = arguCatalogNodesForServiceList.DC;
            }
            if (!string.IsNullOrWhiteSpace(arguCatalogNodesForServiceList.Tag))
            {
                queryParameter.OtherParameters.Add("tag", arguCatalogNodesForServiceList.Tag);
            }
            if (!string.IsNullOrWhiteSpace(arguCatalogNodesForServiceList.Tag))
            {
                queryParameter.OtherParameters.Add("near", arguCatalogNodesForServiceList.Near);
            }
            if (!string.IsNullOrWhiteSpace(arguCatalogNodesForServiceList.NodeMeta))
            {
                queryParameter.OtherParameters.Add("node-meta", arguCatalogNodesForServiceList.NodeMeta);
            }

            return await ApiSend<ResultCatalogNodesForServiceList>(path, queryParameter: queryParameter);

        }

        public async Task Register(ArguCatalogRegister arguCatalogRegister)
        {
            await ApiSendResponse("catalog/register", arguCatalogRegister, EnumConsulHttpMethod.Put, requestHeaders: BuildTokenHeader(new EnumResource[] {
                EnumResource.Node,
                EnumResource.Service
            }));
        }

        public async Task<ResultCatalogServiceList> ServiceList(ArguCatalogServiceList arguCatalogServiceList)
        {
            QueryParameter queryParameter = null;
            if (arguCatalogServiceList != null)
            {
                queryParameter = null;
                if (!string.IsNullOrWhiteSpace(arguCatalogServiceList.DC))
                {
                    queryParameter.Datacenter = arguCatalogServiceList.DC;

                }
                if (!string.IsNullOrWhiteSpace(arguCatalogServiceList.NodeMeta))
                {
                    queryParameter.OtherParameters.Add("node-meta", arguCatalogServiceList.NodeMeta);
                }
            }
            return await ApiSend<ResultCatalogServiceList>("catalog/services", queryParameter: queryParameter);
        }

        public async Task<ResultCatalogServicesForNodeList> ServicesForNodeList(ArguCatalogServicesForNodeList arguCatalogServicesForNodeList)
        {
            var path = $"catalog/node/{arguCatalogServicesForNodeList.Node}";
            var queryParameter = new QueryParameter();
            if (!string.IsNullOrWhiteSpace(arguCatalogServicesForNodeList.DC))
            {
                queryParameter.Datacenter = arguCatalogServicesForNodeList.DC;
            }
            if (!string.IsNullOrWhiteSpace(arguCatalogServicesForNodeList.NodeMeta))
            {
                queryParameter.OtherParameters.Add("node-meta", arguCatalogServicesForNodeList.NodeMeta);
            }

            return await ApiSend<ResultCatalogServicesForNodeList>(path, queryParameter: queryParameter);
        }
    }
}
